package tech.horgee.service;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.horgee.entity.Attendance;
import tech.horgee.mapper.AttendanceMapper;
import tech.horgee.mapper.UserMapper;
import tech.horgee.utils.AssertUtil;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 考勤表 服务类
 *
 * @author haojun
 * @since 2023-12-13
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AttendanceService {
    private final AttendanceMapper mapper;
    private final UserMapper userMapper;

    /**
     * 分页查询列表
     *
     * @param page   分页对象
     * @param entity 查询实体
     * @return 所有数据
     */
    public Page<Attendance> page(Page<Attendance> page, Attendance entity) {
        LambdaQueryWrapper<Attendance> wrapper = Optional.ofNullable(entity).orElse(new Attendance()).wrapper();
        wrapper.orderByDesc(Attendance::getId);
        Page<Attendance> pageData = mapper.selectPage(page, wrapper);
        List<Attendance> records = pageData.getRecords();
        if (records.isEmpty()) return pageData;
        Set<Long> userIds = records.stream().map(Attendance::getUserId).collect(Collectors.toSet());
        Map<Long, String> nameMap = userMapper.getNameMapByIds(userIds);
        List<Attendance> list = records.stream().peek(attend -> {
            attend.setNickname(nameMap.get(attend.getUserId()));
        }).toList();
        pageData.setRecords(list);
        return pageData;
    }

    /**
     * 不分页查询列表
     *
     * @param entity 实体对象
     * @return 查询结果
     */
    public List<Attendance> list(Attendance entity) {
        return mapper.selectList(Optional.ofNullable(entity).orElse(new Attendance()).wrapper());
    }

    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return 单条数据
     */
    public Attendance getById(Long id) {
        return mapper.selectById(id);
    }

    /**
     * 新增单条数据
     *
     * @param entity 实体对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void save(Attendance entity) {
        mapper.insert(entity);
    }

    /**
     * 修改单条数据
     *
     * @param entity 实体对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(Attendance entity) {
        AssertUtil.onlyOne(mapper.updateById(entity));
    }

    /**
     * 批量删除数据
     *
     * @param ids 主键集合
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteByIds(Set<Long> ids) {
        AssertUtil.updated(mapper.deleteBatchIds(ids));
    }

    /**
     * 查询今日打卡记录
     */
    public Attendance getSignTime() {
        Long loginId = StpUtil.getLoginIdAsLong();
        LambdaQueryWrapper<Attendance> queryWrapper = new LambdaQueryWrapper<>();
        return mapper.selectOne(queryWrapper.eq(Attendance::getUserId, loginId)
                .eq(Attendance::getSignDate, LocalDate.now()));
    }

    /**
     * 打卡
     */
    public void signIn(Attendance dto) {
        Long id = dto.getId();
        if (Objects.nonNull(id) && id > 0) {
            dto.setExitTime(LocalTime.now());
            mapper.updateById(dto);
        } else {
            dto.setUserId(StpUtil.getLoginIdAsLong());
            dto.setSignDate(LocalDate.now());
            dto.setSignTime(LocalTime.now());
            mapper.insert(dto);
        }
    }

    /**
     * 考勤异常处理
     */
    public void handleException(Attendance dto) {
        Long id = dto.getId();
        if (Objects.nonNull(id) && id > 0) {
            mapper.updateById(dto);
        } else {
            dto.setUserId(StpUtil.getLoginIdAsLong());
            mapper.insert(dto);
        }
    }

}
